package com.yuanfud.common.util;

import org.jose4j.json.JsonUtil;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.NumericDate;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.lang.JoseException;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class JwtHandler {

        private   JwtHandler(){};

        private  static  String apiKey ="8699a4b0756045c2866da958428f99bf";
        private  static  String publicKeyText = "{\"kty\":\"RSA\",\"kid\":\"8699a4b0756045c2866da958428f99bf\",\"alg\":\"ES256\",\"n\":\"nObc-szhLwnMqRIHytrho7Ihg1WSuKQ8YNzkVbhHxQ83wBe8F7evhsUsIwYT0bAA9-lZOhtPONZHQs4o77ZWnKZcL44c_b_2xbvwn1XGpi-O1knes4g-OnQuKKWC0UY2PXxNcxncPoLAMiyhh8-5P0-sdnnWrCcLNscfj8paM24ZM35U9kczY6M9nSqOurexf6EsA1RpPabgpZ4zVD6IM0T3r7FbsGIg2kTdYGi2E0ODhogJyncp1_H2xvI-11DqrMXNsuvpJgye9CkXk8efKjgOR6h_rVm-45LoH6BHKoVdM5VvE25e1hj_WQA0LdFI5VsbpnzFBhZ5IwB4CUuUVQ\",\"e\":\"AQAB\"}";
        private  static  String privateKeyText = "{\"kty\":\"RSA\",\"kid\":\"8699a4b0756045c2866da958428f99bf\",\"alg\":\"ES256\",\"n\":\"nObc-szhLwnMqRIHytrho7Ihg1WSuKQ8YNzkVbhHxQ83wBe8F7evhsUsIwYT0bAA9-lZOhtPONZHQs4o77ZWnKZcL44c_b_2xbvwn1XGpi-O1knes4g-OnQuKKWC0UY2PXxNcxncPoLAMiyhh8-5P0-sdnnWrCcLNscfj8paM24ZM35U9kczY6M9nSqOurexf6EsA1RpPabgpZ4zVD6IM0T3r7FbsGIg2kTdYGi2E0ODhogJyncp1_H2xvI-11DqrMXNsuvpJgye9CkXk8efKjgOR6h_rVm-45LoH6BHKoVdM5VvE25e1hj_WQA0LdFI5VsbpnzFBhZ5IwB4CUuUVQ\",\"e\":\"AQAB\",\"d\":\"NbRPrwixiwgvpS8mu6hv0zgFgI6pycltYTo6bZzF9A1hZ764AuY8jkSu9s39uqgjrLeScvEmDK5LdfJa0LH4s2W96Akcoz4xmTza_668b-WXXoGqWIkpw5hAtGjyfe8qYaFKYTtYx4y5fHMKVxIitijvPx40_Hfgvr8pbm40saVR5ClXq59idU-EF85abw0buOqP1qGg_OxfjSLqNZbuJPdiXruaTCotTdrXIrshAGe6xnBu051xlbCg62bA4CxqT1eVrx5hiL43cZBh5OybDH-zsL8mo5c_QsKA2iuWET1Q2BUN81SmAu5G0cuGaYQf0XDPGP1_PkVyfKco0DE8AQ\",\"p\":\"88ZWm49IQxsbfeaQRu9O65na1A6Endd75pWe9u9FpBktJ-tZiXg32EXuaZKqX2bH3GwBfFjYgjJlNmkkacPi9M30iiwj40UkiMQ7WUSVrhnnxbEEXTDtCcr6pXBijx2A90jF_BSDPzkLhuGBSjKThHCXrAwBVnJUQJHoe_UD4Ak\",\"q\":\"pMU4khZj766UPZ8FEt8LKSlDgTWd29lqj4AVPwlLv0OpcJCCQ1cnzTw7vIE1tsU3aq9lcUceDDiyeTL9KtEtkSAqUDtSmyk3sk8-9ZNSFDNul6XDo7ugiD7re7FKULzRnNEt9xmMP9i2cYb9XAvrfhfQk6VLUK3_v0yCjvw-zO0\",\"dp\":\"GuSgnVy7Phv5dnQ_KnQwIrHAgHBxlPA2zQNonBldd3MHlkXShOXsU0GzwZXakdfG6LxJlaw_hm2E2PHUgI6JtTQbbDreYq44D5aGbZyxXpmhBiA3OQiyvcfUyveRB_TbS2yN2vdwW0Mx0FmEZ-kYeR3qvaI9a4oFXXI7UaGAIfE\",\"dq\":\"f8B-TR5ZG9PzEhgCehA_egmJUlw86eGXsm1vi7Fsbn5KmIEizo17ybAC7PQNrokYn3ogoASw8m7fSgNTsWf_-X7D7_Me6Di7-19gBE3WHN2HyMJ4frGSFTEbqYrbgN_1ca3qAqVnTXV8d2dfd4eybdCPInrNe199ZFgw_iXrlz0\",\"qi\":\"m2QNSg9d-PhVIjRcOxCXE48zlcCER9nXt_IE7ZbpAQRtotCfj1bVzyjd35MDZznxMVGcn70prs4fQwsn_kF4QnlSB8_GbHj7gD4DI5CJVKf4zK20ekDxN8lhZKEEjzH2K2mZgz7arjLNZEPOZ5YkCnuJPiVl6dap5cNG9B-2dUQ\"}";

        /**
         * 生成jwt token
         * @param
         * @param ip
         * @return
         * @throws JoseException
         */
        public  static Map<String,Object> getJwtToken(HashMap hashMap, String ip) throws JoseException
        {
            Map<String,Object> map = new LinkedHashMap<>();

            String appKey = GuidGenerator.generateUUID();

            JwtClaims claims = new JwtClaims();
            claims.setGeneratedJwtId();
            claims.setIssuedAtToNow();
            //expire time
            NumericDate date = NumericDate.now();
            date.addSeconds(7200);
            claims.setExpirationTime(date);
            claims.setNotBeforeMinutesInThePast(1);
            claims.setSubject((String)hashMap.get("loginId"));
            claims.setAudience("com.yuanfud");
            claims.setClaim("ip",ip);
            claims.setClaim("Id",(Integer)hashMap.get("Id"));
            claims.setClaim("userName",(String) hashMap.get("userName"));
            claims.setClaim("loginId",(String)hashMap.get("loginId"));
            JsonWebSignature jws = new JsonWebSignature();
            jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
            jws.setKeyIdHeaderValue(apiKey);
            jws.setPayload(claims.toJson());
            PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyText)).getPrivateKey();
            jws.setKey(privateKey);
            String idToken = jws.getCompactSerialization();

            //System.out.println(idToken);

            map.put("appKey",appKey);
            map.put("idToken",idToken);
            map.put("Id",hashMap.get("Id"));
            return map;
        }

        /**
         * 验证token
         * @param token
         * @throws JoseException
         * @throws InvalidJwtException
         */
        public static void volatileToken(String token,String loginId) throws JoseException, InvalidJwtException
        {
            PublicKey publicKey = new RsaJsonWebKey(JsonUtil.parseJson(publicKeyText)).getPublicKey();

            JwtConsumer jwtConsumer = new JwtConsumerBuilder()
                    .setRequireExpirationTime() // the JWT must have an expiration time
                    .setMaxFutureValidityInMinutes(120) // but theexpiration time can't be too crazy
                    .setAllowedClockSkewInSeconds(30) // allow some leeway in validating time based claims to account for clock skew
                    //.setExpectedIssuer("csdn.com") // whom the JWT needs to have been issued by
                    .setExpectedAudience("com.yuanfud") // to whom the JWT is intended for
                    .setRequireSubject()
                    .setRequireNotBefore()
                    .setExpectedSubject(loginId)
                    .setVerificationKey(publicKey) // verify the signature with the public key
                    .build(); // create the JwtConsumer instance
            //此处若验证失败 会抛出异常
            JwtClaims jwtClaims = jwtConsumer.processToClaims(token);
            //若无异常出现 则返回true

        }

        public static Map<String, Object> claimsOfToken(String token)
                throws JoseException
        {


            PublicKey publicKey = new RsaJsonWebKey(JsonUtil.parseJson(publicKeyText)).getPublicKey();

            // Validate token signature
            JsonWebSignature jws = new JsonWebSignature();
            jws.setCompactSerialization( token );
            jws.setKey( publicKey );
            if( !jws.verifySignature() )
            {
                throw new JoseException( "JSON Web Token signature verification failed" );
            }

            Map<String, Object> claims = JsonUtil.parseJson( jws.getPayload() );


            return claims;
        }


//        public static  void  main(String args[]) throws JoseException
//        {
//
////
////        Map<String,Object> token = getJwtToken(null,"","192.168.0.2");
////
////        try
////        {
////            Map<String,Object> claims = claimsOfToken((String)token.get("idToken"));
////
////
////
////            System.out.println(claims.get("ip"));
////
////            volatileToken(token.get("idToken").toString(),"admin");
////
////        } catch (InvalidJwtException e)
////        {
////            System.out.println("ssssssssssssss");
////            e.printStackTrace();
////        }
//        }

    }
